package com.cheifsteam.springframework.beans.factory;

import com.cheifsteam.springframework.beans.BeansException;
import com.cheifsteam.springframework.beans.PropertyValue;
import com.cheifsteam.springframework.beans.PropertyValues;
import com.cheifsteam.springframework.beans.factory.config.BeanDefinition;
import com.cheifsteam.springframework.beans.factory.config.BeanFactoryPostProcessor;
import com.cheifsteam.springframework.core.io.DefaultResourceLoader;
import com.cheifsteam.springframework.core.io.Resource;
import com.cheifsteam.springframework.utils.StringValueResolver;

import java.io.IOException;
import java.util.Properties;

/**
 * 属性占位符配置器，用于解析Bean定义中的${...}占位符
 * 实现BeanFactoryPostProcessor接口，在容器初始化阶段处理属性替换
 */
public class PropertyPlaceholderConfigurer implements BeanFactoryPostProcessor {

    /**
     * 默认占位符前缀: "${"
     */
    public static final String DEFAULT_PLACEHOLDER_PREFIX = "${";

    /**
     * 默认占位符后缀: "}"
     */
    public static final String DEFAULT_PLACEHOLDER_SUFFIX = "}";

    /**
     * 属性文件位置
     */
    private String location;

    /**
     * 核心方法：处理Bean工厂中的属性占位符
     * @param beanFactory 可配置的Bean工厂实例
     * @throws BeansException 如果处理过程中出现错误
     */
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        try {
            // 1. 加载属性文件
            DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
            Resource resource = resourceLoader.getResource(location);
            Properties properties = new Properties();
            properties.load(resource.getInputStream());

            // 2. 遍历所有Bean定义
            String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
            for (String beanDefinitionName : beanDefinitionNames) {
                BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanDefinitionName);

                // 3. 处理每个Bean的属性值
                PropertyValues propertyValues = beanDefinition.getPropertyValues();
                for (PropertyValue propertyValue : propertyValues.getPropertyValues()) {
                    Object value = propertyValue.getValue();

                    // 4. 只处理String类型的属性值
                    if (!(value instanceof String)) {
                        continue;
                    }

                    String strVal = (String) value;
                    StringBuilder builder = new StringBuilder(strVal);

                    // 5. 查找占位符位置
                    int startIdx = strVal.indexOf(DEFAULT_PLACEHOLDER_PREFIX);
                    int endIdx = strVal.indexOf(DEFAULT_PLACEHOLDER_SUFFIX);

                    // 6. 如果找到合法占位符则进行替换
                    if (startIdx != -1 && endIdx != -1 && startIdx < endIdx) {
                        // 提取属性key（去掉${和}）
                        String propKey = strVal.substring(startIdx + 2, endIdx);
                        // 从属性文件中获取实际值
                        String propVal = properties.getProperty(propKey);
                        // 替换占位符
                        builder.replace(startIdx, endIdx + 1, propVal);
                        // 更新Bean定义中的属性值
                        propertyValues.addPropertyValue(
                                new PropertyValue(propertyValue.getName(), builder.toString()));
                    }
                }
            }

            // 7. 注册字符串解析器，用于后续处理@Value注解
            StringValueResolver valueResolver = new PlaceholderResolvingStringValueResolver(properties);
            beanFactory.addEmbeddedValueResolver(valueResolver);

        } catch (IOException e) {
            throw new BeansException("无法加载属性文件: " + location, e);
        }
    }

    /**
     * 设置属性文件位置
     * @param location 属性文件路径（支持classpath:、file:等前缀）
     */
    public void setLocation(String location) {
        this.location = location;
    }

    /**
     * 解析单个占位符值
     * @param value 包含占位符的字符串
     * @param properties 已加载的属性集合
     * @return 解析后的字符串
     */
    private String resolvePlaceholder(String value, Properties properties) {
        String strVal = value;
        StringBuilder buffer = new StringBuilder(strVal);

        // 查找占位符位置
        int startIdx = strVal.indexOf(DEFAULT_PLACEHOLDER_PREFIX);
        int stopIdx = strVal.indexOf(DEFAULT_PLACEHOLDER_SUFFIX);

        // 验证占位符是否合法
        if (startIdx != -1 && stopIdx != -1 && startIdx < stopIdx) {
            // 提取属性key
            String propKey = strVal.substring(startIdx + 2, stopIdx);
            // 获取属性值
            String propVal = properties.getProperty(propKey);
            // 执行替换
            buffer.replace(startIdx, stopIdx + 1, propVal);
        }
        return buffer.toString();
    }

    /**
     * 内部类：占位符字符串值解析器
     * 用于处理@Value注解中的${...}表达式
     */
    private class PlaceholderResolvingStringValueResolver implements StringValueResolver {
        private final Properties properties;

        public PlaceholderResolvingStringValueResolver(Properties properties) {
            this.properties = properties;
        }

        /**
         * 解析字符串值
         * @param strVal 包含占位符的字符串
         * @return 解析后的字符串
         */
        @Override
        public String resolveStringValue(String strVal) {
            return PropertyPlaceholderConfigurer.this.resolvePlaceholder(strVal, properties);
        }
    }
}
